package com.cd.university.config.security;

import com.cd.university.config.security.authentication.FormAuthenticationConfig;
import com.cd.university.config.security.authentication.email.EmailCodeAuthenticationSecurityConfig;
import com.cd.university.config.security.authentication.filter.JsonUsernamePasswordAuthenticationFilter;
import com.cd.university.config.security.authentication.jwt.JwtAuthenticationFilter;
import com.cd.university.config.security.authentication.logout.LogoutSecurityConfig;
import com.cd.university.config.security.authentication.sms.SmsCodeAuthenticationSecurityConfig;
import com.cd.university.config.security.properties.SecurityConstants;
import com.cd.university.config.security.validate.ValidateCodeSecurityConfig;
import com.cd.university.config.swagger.SwaggerSecurityConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

/**
 * Security的Web相关配置
 * @author 陈栋
 * @create 2021/9/3 18:31
 */
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class securityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 表单登录的security配置
     */
    @Autowired
    private FormAuthenticationConfig formAuthenticationConfig;

    /**
     * 退出登录的security配置
     */
    @Autowired
    private LogoutSecurityConfig logoutSecurityConfig;

    /**
     * Swagger的Security配置
     */
    @Autowired
    private SwaggerSecurityConfig swaggerSecurityConfig;

    /**
     * 登陆成功处理器
     */
    @Autowired
    private AuthenticationSuccessHandler cdAuthenticationSuccessHandler;

    /**
     * 登陆失败处理器
     */
    @Autowired
    private AuthenticationFailureHandler cdAuthenticationFailureHandler;

    /**
     * 验证码过滤器
     */
    @Autowired
    private ValidateCodeSecurityConfig validateCodeSecurityConfig;

    /**
     * 邮件配置类
     */
    @Autowired
    private EmailCodeAuthenticationSecurityConfig emailCodeAuthenticationSecurityConfig;

    /**
     * 电话配置类
     */
    @Autowired
    private SmsCodeAuthenticationSecurityConfig smsCodeAuthenticationSecurityConfig;

    /**
     * Jwt的验证过滤器
     */
    @Autowired
    private JwtAuthenticationFilter jwtAuthenticationFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 表单登录相关配置
        formAuthenticationConfig.configure(http);
        // 退出登录相关配置
        logoutSecurityConfig.configure(http);
        // Swagger相关配置
        swaggerSecurityConfig.configure(http);

        // 静态资源以及druid的放行
        http
                .authorizeRequests()
                .antMatchers("/css/**", "/js/**","/image/**","/lib/**",  "**/favicon.ico","/", "/index", "/toLogin", "/fail", "/druid/**").permitAll();

        http
                .addFilterAt(jsonUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(jwtAuthenticationFilter, JsonUsernamePasswordAuthenticationFilter.class);

        http
                .apply(validateCodeSecurityConfig)
                    .and()
                .apply(emailCodeAuthenticationSecurityConfig)
                    .and()
                .apply(smsCodeAuthenticationSecurityConfig)
                    .and()
                .authorizeRequests()
                    .antMatchers(
                            "/test/*",
                            // 找回密码的接口
                            SecurityConstants.DEFAULT_RETRIEVE_PASSWORD,
                            // 表单登录页
                            SecurityConstants.DEFAULT_SIGN_IN_PROCESSING_URL_FORM,
                            // 邮件登录
                            SecurityConstants.DEFAULT_SIGN_IN_PROCESSING_URL_EMAIL,
                            // 短信登录
                            SecurityConstants.DEFAULT_SIGN_IN_PROCESSING_URL_MOBILE,
                            // 登陆失败处理页
                            SecurityConstants.DEFAULT_UNAUTHENTICATION_URL,
                            // 用户注册
                            SecurityConstants.DEFAULT_USER_REGISTER,
                            // 生成验证码的url，如/code/sms,/code/iamge等等
                            SecurityConstants.DEFAULT_VALIDATE_CODE_URL_PREFIX+"/*").permitAll()
                    .anyRequest()
                    .authenticated()
                    .and()
                .cors()
                    .and()
                .csrf().disable();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        //        解除swagger配置的限制
        swaggerSecurityConfig.configure(web);
    }


    @Bean
    public JsonUsernamePasswordAuthenticationFilter jsonUsernamePasswordAuthenticationFilter() throws Exception {
        JsonUsernamePasswordAuthenticationFilter authenticationFilter = new JsonUsernamePasswordAuthenticationFilter();
        authenticationFilter.setAuthenticationSuccessHandler(cdAuthenticationSuccessHandler);
        authenticationFilter.setAuthenticationFailureHandler(cdAuthenticationFailureHandler);
        authenticationFilter.setAuthenticationManager(authenticationManagerBean());
        return authenticationFilter;
    }
}

